import java.util.Map;

class GraphContainer{
  PImage img = loadImage("graph2.jpg");
 // println("debug1");
  boolean fillGraph=false;
  boolean grid=true;
  boolean background=false;
  boolean zoomYear=false;
 //   println("debug2");
  color axisLabelsColor=color(160,0,240);
  //  println("debug3");
  //Widths and Heights
  final int marginX=40;
  final int marginY=30;
  final int twidth=40;
  final int theight=25;
  int gwidth=0,gheight=0;
  int _height=100,_width=100;
  //  println("debug4");
  //Starting points to graph, tags and windows
  int sX=0,sY=0;
  int gsx=0,gsy=0;
  int tsx=0,tsy=0;
  

  int idGraph=0;
  
  //minimum and maximum values
  int minValuePopularity=-1,maxValuePopularity=-1;
  int minValueLength=-1,maxValueLength=-1;
  int minYear=-1,maxYear=-1;
  int minZYear=-1,maxZYear=-1;
  int drawingYearMin=-1,drawingYearMax=-1;
  int deltaX=-1,thresholdX=20;
  //  println("debug5");
  //Data Arrays
 // ArrayList<Film> fList;
  ArrayList<Integer> years=new ArrayList<Integer>();
  ArrayList<Graph> graphs=new ArrayList<Graph>();
  
  GraphType gType=new GraphType(GraphType.POPULARITY);
   // println("debug6");
  
  private GraphContainer()
  {
  }
  public GraphContainer(int startingX,int startingY,int windowsWidth,int windowsHeight,GraphType graphType)
  {
    println(startingX,startingY,windowsWidth,windowsHeight,gType.toString());
    sX=startingX;
    sY=startingY+windowsHeight;
    _width=windowsWidth;
    _height=windowsHeight;
    gsx=sX+marginX;
    gsy=sY-marginY;
    
    //twidth=(int)(tagWindowWidth*_width);
    //theight=(int)(tagPercHeight*_height);
    
    gwidth=_width-3*marginX-twidth;
    gheight=_height-2*marginY;
    
    tsx=gsx+gwidth+marginX*3/4;
    tsy=gsy;
    
   // fList=new ArrayList<Film>();
    graphs=new ArrayList<Graph>();
    years=new ArrayList<Integer>();
    
    gType=graphType;

  }
  void AddGraph(ArrayList<film> graphFilmList,String genre,color c)
  {
    
    
    println();
    int n;
    float vPop,vLen;
    HashMap<Integer,Integer> yearsCoef=new HashMap<Integer,Integer>();
    println(graphFilmList.size());
    Graph g=new Graph();
    g.id=idGraph++;
    g.graphColor=c;//il faut generer ca
    g.genre=genre;
    g.gPopularity=new HashMap<Integer,Float>();
    g.gLength=new HashMap<Integer,Float>();
    for(film f:graphFilmList)
    {
        //if(!g.gPopularity.containsKey(f.year))
       // g.gPopularity.put(f.year,(float)f.popularity);
        //if(!g.gLength.containsKey(f.year))
       // g.gLength.put(f.year,(float)f.leng);
        if(!yearsCoef.containsKey(f.year))
        {
            yearsCoef.put(f.year,1);
            g.gPopularity.put(f.year,(float)f.popularity);
            g.gLength.put(f.year,(float)f.leng);
        }
      
      else
      {
        vPop=g.gPopularity.get(f.year);
        vLen=g.gLength.get(f.year);
        n=yearsCoef.get(f.year);
        
        n++;
        vPop+=f.popularity;       
        vLen+=f.leng;
        
        yearsCoef.put(f.year,n);
        g.gPopularity.put(f.year,vPop);
        g.gLength.put(f.year,vLen);
      }
    }
    //normalizing genres
    for(int year:yearsCoef.keySet())
    {
      if(!years.contains(year))
          years.add(year);
      if(minYear==-1||maxYear==-1)
         {
           minYear=year;
           maxYear=year;
         }
      else
      {
        if(year<minYear)
          minYear=year;
          if(year>maxYear)
          maxYear=year;
        
      }
      
      n=yearsCoef.get(year);
      vPop=g.gPopularity.get(year);
      vLen=g.gLength.get(year);
      
      vPop=vPop/n;
      vLen=vLen/n;
      

      g.gPopularity.put(year,vPop);
      g.gLength.put(year,vLen);
      
            //Initializing and updating min and max
            
            //Popularity min and max
              if(minValuePopularity==-1)
                      minValuePopularity=(int)vPop;
               else if (minValuePopularity>vPop)
               {
                 minValuePopularity=(int)vPop;
               }
               
               if(maxValuePopularity==-1)
                      maxValuePopularity=(int)vPop;
               else if (maxValuePopularity<vPop)
               {
                 maxValuePopularity=(int)vPop;
               }
    //Length Min and Max
               if(minValueLength==-1)
                      minValueLength=(int)vLen;
               else if (minValueLength>vLen)
               {
                 minValueLength=(int)vLen;
               }
               
               if(maxValueLength==-1)
                      maxValueLength=(int)vLen;
               else if (maxValueLength<vLen)
               {
                 maxValueLength=(int)vLen;
               }
    }
    
    graphs.add(g);
    
  }
  void Draw()
  { 
    
    println(sX,sY,_width,_height);
    if(!background)
    {
    axisLabelsColor=color(160,0,240);
    fill(0,0,0); 
    rect(sX,sY-_height,_width,_height);
    }
    else
    {
      axisLabelsColor=color(80,240,120);
      image(img,sX,sY-_height,_width,_height);
    }
    println(zoomYear);
    if(zoomYear)
    {
      println("zoomed");
      drawingYearMin=minZYear;
      drawingYearMax=maxZYear;
    }
    else
    {
      drawingYearMin=minYear;
      drawingYearMax=maxYear;
    }
    if(drawingYearMin==drawingYearMax)
    return;
    DrawAxis();
    for(Graph g:graphs)
      DrawGraph(g);
    DrawTags();
    
  }
  void DrawGraph(Graph g)
  {
    float valueOld=-1.0f;
    int yearOld=-1;
    float value;
    //println(minYear,maxYear);
    fill(g.graphColor);
    strokeWeight(2);
    stroke(g.graphColor);
    for(int year=drawingYearMin;year<=drawingYearMax;year++)
    {
       if(!g.gPopularity.containsKey(year))
            continue;
       
       if(gType.isPopularity())
       value=g.gPopularity.get(year);
       else
       value=g.gLength.get(year);
       
       if(yearOld==-1||valueOld==-1.0f)
             {
               yearOld=year;
               valueOld=value;
               continue;
             }

        DrawLine(valueOld,value,yearOld,year);
        valueOld=value;
        yearOld=year;  
    }
  }
  void DrawLine(float value1,float value2,int year1,int year2)
  { 
   // println("Drawing "+value1+" "+value2+" "+year1+" "+year2);
    int y1=0,y2=0,x1=0,x2=0;
    x1=(int)((year1-drawingYearMin)*gwidth/(drawingYearMax-drawingYearMin) + gsx);
    x2=(int)((year2-drawingYearMin)*gwidth/(drawingYearMax-drawingYearMin) + gsx);
    if(gType.isPopularity())
    {
      if(fillGraph)
      {
    y1=mapPop(value1);
    y2=mapPop(value2);
      }
    else
    {
    y1=(int)(-(value1)*gheight/(100) + gsy);
    y2=(int)(-(value2)*gheight/(100) + gsy);
    }
    
    }
    else if(gType.isLength())
    {

    y1=mapLen(value1);
    y2=mapLen(value2);
    
    }
    
    
    line(x1,y1,x2,y2); 
  }
    void DrawAxis()
  {
    fill(axisLabelsColor);
    stroke(axisLabelsColor);
    //println(gsx,gsy,gsx+gwidth,gsy);
    //println(gsx,gsy,gsx,gsy-gheight);
    strokeWeight(4);
    
    //X axis
    line(gsx,gsy,gsx+gwidth,gsy);
    textSize(16);
    text("Year",gsx+gwidth+20,gsy+5);
   
    int x,y;


    //Y  axis
    line(gsx,gsy,gsx,gsy-gheight);
    textSize(16);
    text(gType.toString(),gsx,gsy-gheight-10);
    
    //Y Length axis
   // if(minValueLength!=-1)
    //line(gsx+gwidth,gsy,gsx+gwidth,gsy-gheight);
    
    DrawLabels();
    strokeWeight(1);
    if(grid)
      DrawGrid();
  }
  void DrawLabels()
  {  textSize(12);
    fill(axisLabelsColor);
    int x,y;
    deltaX=0;
    int stepYear=0;
    while(deltaX<thresholdX)
    {
     stepYear+=1;
    deltaX=mapYear(2000+stepYear)-mapYear(2000);
      
    }
              //Drawing X Labels
        for(int year=drawingYearMin;year<=drawingYearMax;year+=stepYear)
    {  
      x=mapYear(year);
      line(x,gsy-5,x,gsy+5);
      text(""+year%100,x,gsy+20);
    }
    
    if(gType.isPopularity())
    {
      if(fillGraph)
      {
                  //Drawing Y Labels
          int step=(maxValuePopularity-minValuePopularity)*10/100;
        for(int value=minValuePopularity;value<=maxValuePopularity;value+=step)
          {     y=mapPop(value);
                line(gsx-5,y,gsx+5,y);
                text(""+value,gsx-25,y);
          }
      }
      else
      {
                          //Drawing Y Labels
        int step=10;
        for(int value=0;value<=100;value+=step)
          {     y=(int)(-(value)*gheight/(100) + gsy);
                line(gsx-5,y,gsx+5,y);
                text(""+value,gsx-25,y);
           }
        
      }
    }
    else
    if(gType.isLength())
    {
    //drawin length labels
      if(minValueLength!=-1)
     {
                        //Drawing Y Labels
        int step=(maxValueLength-minValueLength)*10/100;
        for(int value=minValueLength;value<=maxValueLength;value+=step)
        {  y=mapLen(value);
           line(gsx-5,y,gsx+5,y);
           text(""+value,gsx-25,y);;
        }
      }
      
    }
    
  }
  void DrawGrid()
  {
    fill(axisLabelsColor,128);
    stroke(axisLabelsColor,128);
    int x,y;
            for(int year=drawingYearMin;year<=drawingYearMax;year+=5)
    {  
      x=mapYear(year);
      line(x,gsy,x,gsy-gheight);
    }
                  //Drawing Y Labels
        int step=10;
    for(int value=0;value<=100;value+=3*step)
    {  y=(int)(-(value)*gheight/(100) + gsy);
      line(gsx,y,gsx+gwidth,y);
    }
    
  }
  void DrawTags()
  {
    int i=0;
    for(Graph g:graphs)
    {
        fill(g.graphColor);
        stroke(g.graphColor);
        rect(tsx,tsy-2*(i+1)*theight,twidth,theight,7);
        fill(axisLabelsColor);
        stroke(0,0,0);
        text(g.genre+" "+gType.toString(),tsx,tsy-2*(i+1)*theight-10);
        i++;
    }
    
  }
  void selectYear(int zoomYearMin,int zoomYearMax)
  {
    println("year selected");
    zoomYear=true;
    minZYear=zoomYearMin;
    maxZYear=zoomYearMax;
    
  }
  void Move(int newX,int newY)
  {
    sX=newX;
    sY=newY;
    gsx=sX+marginX;
    gsy=sY-marginY;
    tsx=gsx+gwidth+marginX*3/4;
    tsy=gsy;
    Draw();
  }
  
  int mapYear(int year)
  {println(drawingYearMax,drawingYearMin);
   if(drawingYearMax==drawingYearMin)
     return 0;
    return (int)((year-drawingYearMin)*gwidth/(drawingYearMax-drawingYearMin) + gsx);
  }
  int mapPop(float value)
  {
    return  (int)(-(value-minValuePopularity)*gheight/(maxValuePopularity-minValuePopularity) + gsy);
  }
  int mapLen(float value)
  {
    return (int)(-(value-minValueLength)*gheight/(maxValueLength-minValueLength) + gsy);
  }
  
  void Resize(int w,int h)
  {
    sX=sX;
    sY=sY-_height+h;
    _width=w;
    _height=h;
    gsx=sX+marginX;
    gsy=sY-marginY;
    
    //twidth=(int)(tagWindowWidth*_width);
    //theight=(int)(tagPercHeight*_height);
    
    gwidth=_width-3*marginX-twidth;
    gheight=_height-2*marginY;
    
    tsx=gsx+gwidth+marginX*3/4;
    tsy=gsy;
  }

  
}
